
#pragma once

#include "StandardShape.h"

namespace Ipc2581b
{

class Butterfly;
class Circle;
class Contour;
class Diamond;
class Donut;
class Ellipse;
class Hexagon;
class Moire;
class Octagon;
class Oval;
class RectCenter;
class RectCham;
class RectCorner;
class RectRound;
class Thermal;
class Triangle;

class StandardPrimitive: public StandardShape
{
public:
	virtual ~StandardPrimitive() {}

    enum class StandardPrimitiveType
    {
        Butterfly
        ,Circle
        ,Contour
        ,Diamond
        ,Donut
        ,Ellipse
        ,Hexagon
        ,Moire
        ,Octagon
        ,Oval
        ,RectCenter
        ,RectCham
        ,RectCorner
        ,RectRound
        ,Thermal
        ,Triangle
    };

    virtual StandardPrimitiveType standardPrimitiveType() const = 0;

    inline bool isButterfly() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Butterfly;
    }

    inline Butterfly *toButterfly()
    {
        return reinterpret_cast<Butterfly*>(this);
    }

    inline const Butterfly *toButterfly() const
    {
        return reinterpret_cast<const Butterfly*>(this);
    }

    inline bool isCircle() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Circle;
    }

    inline Circle *toCircle()
    {
        return reinterpret_cast<Circle*>(this);
    }

    inline const Circle *toCircle() const
    {
        return reinterpret_cast<const Circle*>(this);
    }

    inline bool isContour() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Contour;
    }

    inline Contour *toContour()
    {
        return reinterpret_cast<Contour*>(this);
    }

    inline const Contour *toContour() const
    {
        return reinterpret_cast<const Contour*>(this);
    }

    inline bool isDiamond() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Diamond;
    }

    inline Diamond *toDiamond()
    {
        return reinterpret_cast<Diamond*>(this);
    }

    inline const Diamond *toDiamond() const
    {
        return reinterpret_cast<const Diamond*>(this);
    }

    inline bool isDonut() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Donut;
    }

    inline Donut *toDonut()
    {
        return reinterpret_cast<Donut*>(this);
    }

    inline const Donut *toDonut() const
    {
        return reinterpret_cast<const Donut*>(this);
    }

    inline bool isEllipse() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Ellipse;
    }

    inline Ellipse *toEllipse()
    {
        return reinterpret_cast<Ellipse*>(this);
    }

    inline const Ellipse *toEllipse() const
    {
        return reinterpret_cast<const Ellipse*>(this);
    }

    inline bool isHexagon() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Hexagon;
    }

    inline Hexagon *toHexagon()
    {
        return reinterpret_cast<Hexagon*>(this);
    }

    inline const Hexagon *toHexagon() const
    {
        return reinterpret_cast<const Hexagon*>(this);
    }

    inline bool isMoire() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Moire;
    }

    inline Moire *toMoire()
    {
        return reinterpret_cast<Moire*>(this);
    }

    inline const Moire *toMoire() const
    {
        return reinterpret_cast<const Moire*>(this);
    }

    inline bool isOctagon() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Octagon;
    }

    inline Octagon *toOctagon()
    {
        return reinterpret_cast<Octagon*>(this);
    }

    inline const Octagon *toOctagon() const
    {
        return reinterpret_cast<const Octagon*>(this);
    }

    inline bool isOval() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Oval;
    }

    inline Oval *toOval()
    {
        return reinterpret_cast<Oval*>(this);
    }

    inline const Oval *toOval() const
    {
        return reinterpret_cast<const Oval*>(this);
    }

    inline bool isRectCenter() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::RectCenter;
    }

    inline RectCenter *toRectCenter()
    {
        return reinterpret_cast<RectCenter*>(this);
    }

    inline const RectCenter *toRectCenter() const
    {
        return reinterpret_cast<const RectCenter*>(this);
    }

    inline bool isRectCham() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::RectCham;
    }

    inline RectCham *toRectCham()
    {
        return reinterpret_cast<RectCham*>(this);
    }

    inline const RectCham *toRectCham() const
    {
        return reinterpret_cast<const RectCham*>(this);
    }

    inline bool isRectCorner() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::RectCorner;
    }

    inline RectCorner *toRectCorner()
    {
        return reinterpret_cast<RectCorner*>(this);
    }

    inline const RectCorner *toRectCorner() const
    {
        return reinterpret_cast<const RectCorner*>(this);
    }

    inline bool isRectRound() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::RectRound;
    }

    inline RectRound *toRectRound()
    {
        return reinterpret_cast<RectRound*>(this);
    }

    inline const RectRound *toRectRound() const
    {
        return reinterpret_cast<const RectRound*>(this);
    }

    inline bool isThermal() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Thermal;
    }

    inline Thermal *toThermal()
    {
        return reinterpret_cast<Thermal*>(this);
    }

    inline const Thermal *toThermal() const
    {
        return reinterpret_cast<const Thermal*>(this);
    }

    inline bool isTriangle() const
    {
        return standardPrimitiveType() == StandardPrimitiveType::Triangle;
    }

    inline Triangle *toTriangle()
    {
        return reinterpret_cast<Triangle*>(this);
    }

    inline const Triangle *toTriangle() const
    {
        return reinterpret_cast<const Triangle*>(this);
    }

    virtual StandardShapeType standardShapeType() const override
    {
        return StandardShapeType::StandardPrimitive;
    }

};

}

// For user convenience
#include "Butterfly.h"
#include "Circle.h"
#include "Contour.h"
#include "Diamond.h"
#include "Donut.h"
#include "Ellipse.h"
#include "Hexagon.h"
#include "Moire.h"
#include "Octagon.h"
#include "Oval.h"
#include "RectCenter.h"
#include "RectCham.h"
#include "RectCorner.h"
#include "RectRound.h"
#include "Thermal.h"
#include "Triangle.h"
